package com.icekrvams.billing.utilities

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.ProductDetails
import com.android.billingclient.api.ProductDetailsResult
import com.android.billingclient.api.Purchase
import com.android.billingclient.api.Purchase.PurchaseState
import com.icekrvams.billing.BillingFlowDraftCallback
import com.icekrvams.billing.data.DataHolder

internal object BillingUtilities {

    /**
     * 如果已有用 [product] 对应的商品，将其返回。
     * @param purchases 已拥有的商品。
     * @param product 查询是否已经有用该商品。
     */
    fun purchaseForProduct(
        purchases: List<Purchase>?,
        product: String
    ): Purchase? {
        return purchases?.let {
            it.findLast { purchase ->
                purchase.purchaseState == PurchaseState.PURCHASED && purchase.products[0] == product
            }
        }
    }

    /**
     * 是否已经拥有了 [product] 对应的商品。
     * @param purchases 已拥有的商品。
     * @param product 当前查询商品。
     */
    fun deviceIsPurchaseOwned(
        purchases: List<Purchase>?,
        product: String
    ): Boolean {
        return purchaseForProduct(purchases, product) != null
    }

    /**
     * 已经拥有的订阅商品。
     */
    fun deviceOwnedSubscriptions(): List<String> {
        val ownedProducts = mutableListOf<String>()
        DataHolder.products.allSubProducts.forEach {
            if (purchaseForProduct(DataHolder.purchases, it) != null) {
                ownedProducts.add(it)
            }
        }
        return ownedProducts
    }

    /**
     * 已经拥有的订阅商品和一次性购买商品。
     */
    fun deviceOwnedProducts(): List<String> {
        val ownedProducts = mutableListOf<String>()
        (DataHolder.products.allOneTimeIapProducts + DataHolder.products.allSubProducts).forEach {
            if (purchaseForProduct(DataHolder.purchases, it) != null) {
                ownedProducts.add(it)
            }
        }
        return ownedProducts
    }

    /**
     * 启动 PlayStore 订阅管理页面，常用于出现重复订阅时或引导用户取消订阅。
     * @see BillingFlowDraftCallback.onShouldGoToSubManagePage
     */
    fun openPlayStoreSubManagementPage(
        context: Context,
        product: String? = null
    ) {
        "Viewing subscriptions on the Google Play Store".iLog()
        val url = if (product == null) {
            // If the Product is not specified, just open the Google Play subscriptions URL.
            Constants.PLAY_STORE_SUBSCRIPTION_URL
        } else {
            // If the Product is specified, open the deeplink for this Product on Google Play.
            String.format(
                Constants.PLAY_STORE_SUBSCRIPTION_DEEPLINK_URL,
                product,
                context.packageName
            )
        }
        val intent = Intent(Intent.ACTION_VIEW)
            .setData(Uri.parse(url))
        if (context !is Activity) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }

    /**
     * 当未配置订阅商品或者内购商品，直接对对应商品的查询结果定义为成功，商品信息为空。
     * @param type 商品类型。
     */
    fun generateEmptyProductDetailsResult(@BillingClient.ProductType type: String): ProductDetailsResult {
        val billingResult =
            BillingResult.newBuilder()
                .setResponseCode(BillingClient.BillingResponseCode.OK)
                .setDebugMessage("Available $type product param isn't set")
                .build()
        return ProductDetailsResult(billingResult, emptyList())
    }

    /**
     * 判断已存在的订阅商品，是否可被替换（升降级）。
     */
    fun isOldProductReplaceable(
        purchases: List<Purchase>?,
        oldProduct: String?
    ): Boolean {
        return if (oldProduct == null) false else deviceIsPurchaseOwned(
            purchases,
            oldProduct
        )
    }

    /**
     * 获取可用的 OfferToken。
     * @param offerToken 客户端传入的（用户选择的优惠方式） OfferToken。
     */
    fun getAvailableOfferToken(
        productDetails: ProductDetails,
        offerToken: String?
    ): String? {
        if (offerToken != null) return offerToken
        return leastPricedOfferToken(productDetails)
    }

    /**
     * 查询价格最低的优惠策略的 offerToken。
     */
    private fun leastPricedOfferToken(
        productDetails: ProductDetails
    ): String? {
        val offerDetails = productDetails.subscriptionOfferDetails
        var offerToken: String? = null
        var lowestPrice = Long.MAX_VALUE
        if (!offerDetails.isNullOrEmpty()) {
            offerDetails.forEach { offer ->
                offer.pricingPhases.pricingPhaseList.forEach { price ->
                    if (price.priceAmountMicros < lowestPrice) {
                        lowestPrice = price.priceAmountMicros
                        offerToken = offer.offerToken
                    }
                }
            }
        }
        return offerToken
    }

    /**
     * 查询价格最低的优惠策略的展示价格。
     */
    private fun leastPriceFormatted(
        productDetails: ProductDetails
    ): String? {
        val offerDetails = productDetails.subscriptionOfferDetails
        var formattedPrice: String? = null
        var lowestPrice = Long.MAX_VALUE
        if (!offerDetails.isNullOrEmpty()) {
            offerDetails.forEach { offer ->
                offer.pricingPhases.pricingPhaseList.forEach { price ->
                    if (price.priceAmountMicros in 1 until lowestPrice) {
                        lowestPrice = price.priceAmountMicros
                        formattedPrice = price.formattedPrice
                    }
                }
            }
        }
        return formattedPrice
    }

    /**
     * 获取商品价格信息。
     * @param product 商品 Id。
     */
    fun getFormattedPrice(product: String): String? {
        val productDetails = DataHolder.productWithProductDetails[product] ?: return null
        return if (DataHolder.products.availableSubProducts.contains(product)) {
            leastPriceFormatted(productDetails)
        } else {
            productDetails.oneTimePurchaseOfferDetails?.formattedPrice
        }
    }

    /**
     * 查询价格最低的优惠策略的价格。
     */
    private fun leastPriceAmountMicros(
        productDetails: ProductDetails,
    ): Long? {
        val offerDetails = productDetails.subscriptionOfferDetails
        var lowestPrice = Long.MAX_VALUE
        if (!offerDetails.isNullOrEmpty()) {
            offerDetails.forEach { offer ->
                offer.pricingPhases.pricingPhaseList.forEach { price ->
                    if (price.priceAmountMicros in 1 until lowestPrice) {
                        lowestPrice = price.priceAmountMicros
                    }
                }
            }
        }
        return if (lowestPrice == Long.MAX_VALUE) null else lowestPrice
    }

    /**
     * 获取商品价格。
     * @param product 商品 Id。
     */
    fun getPrice(product: String): Double? {
        val priceAmountMicros = getOriginalPrice(product)
        return if (priceAmountMicros == null) {
            null
        } else {
            priceAmountMicros / 1000000.0
        }
    }

    /**
     * 获取 Billing API 返回的商品价格。该价格是实际价格的 1000000 倍。
     * @param product 商品 Id。
     */
    fun getOriginalPrice(product: String): Long? {
        val productDetails = DataHolder.productWithProductDetails[product] ?: return null
        val priceAmountMicros = if (DataHolder.products.availableSubProducts.contains(product)) {
            leastPriceAmountMicros(productDetails)
        } else {
            productDetails.oneTimePurchaseOfferDetails?.priceAmountMicros
        }
        return priceAmountMicros
    }

    /**
     * 获取商品价格货币单位。
     * @param product 商品 Id。
     */
    fun getPriceCurrencyCode(product: String): String? {
        val productDetails = DataHolder.productWithProductDetails[product] ?: return null
        return if (DataHolder.products.availableSubProducts.contains(product)) {
            leastPriceCurrencyCode(productDetails)
        } else {
            productDetails.oneTimePurchaseOfferDetails?.priceCurrencyCode
        }
    }

    /**
     * 查询价格最低的优惠策略的价格货币单位。
     */
    private fun leastPriceCurrencyCode(
        productDetails: ProductDetails,
    ): String? {
        val offerDetails = productDetails.subscriptionOfferDetails
        var lowestPrice = Long.MAX_VALUE
        var priceCurrencyCode: String? = null
        if (!offerDetails.isNullOrEmpty()) {
            offerDetails.forEach { offer ->
                offer.pricingPhases.pricingPhaseList.forEach { price ->
                    if (price.priceAmountMicros in 1 until lowestPrice) {
                        lowestPrice = price.priceAmountMicros
                        priceCurrencyCode = price.priceCurrencyCode
                    }
                }
            }
        }
        return priceCurrencyCode
    }
}
